-- Copyright (C) 2013
--vss.workflow.upload is not OK

-------1定义公共组件(开�?---------------

local cjson = require "cjson"
local storage    = require("resty.gcsdfs.storage")              --加载storage �?
local red_method = require("gcs.list.method")
local iconv = require("iconv")
local utils   = require "gcs.utils"
local mongo_method  = require "gcs.mongodb.method"
local str_sub  = string.sub
local str_find = string.find
local str_len  = string.len
local tb_concat  = table.concat
local tb_getn = table.getn
local tb_insert = table.insert
local table = table
local type  = type
local pairs = pairs
local ngx = ngx
local os  = os
local string = string
local math_floor = math.floor
local math_random   =math.random
local math_abs    =math.abs
local tostring  = tostring
local tonumber  = tonumber
local cjson = require "cjson"
local vssid = "upload_utils"
local model = "upload_hkkk"
local error_table = ngx.shared.gcs_error   --声明ngx.shared.gcs_error
local config_table             = ngx.shared.gcs_config            --定义gcs_config缓存
local ipshine_table = ngx.shared.gcs_ipshine
local resty_uuid               = require "resty.uuid"

----------------定义相关的表--------------------
local tb_csys = {}
tb_csys[0]= "未知颜色"
tb_csys[1]= "白色"
tb_csys[2]= "银色"
tb_csys[3]= "灰色"
tb_csys[4]= "黑色"
tb_csys[5]= "红色"
tb_csys[6]= "深蓝"
tb_csys[7]= "蓝色"
tb_csys[8]= "黄色"
tb_csys[9]= "绿色"
tb_csys[10]= "棕色"
tb_csys[11]= "粉色"
tb_csys[12]= "紫色"
local tb_clpp = {}
tb_clpp[0]= "未知品牌"
tb_clpp[1]= "大众"
tb_clpp[2]= "别克"
tb_clpp[3]= "宝马"
tb_clpp[4]= "本田"
tb_clpp[5]= "标致"
tb_clpp[6]= "丰田"
tb_clpp[7]= "福特"
tb_clpp[8]= "日产"
tb_clpp[9]= "奥迪"
tb_clpp[10]= "马自达"
tb_clpp[11]= "雪弗兰"
tb_clpp[12]= "雪铁龙"
tb_clpp[13]= "现代"
tb_clpp[14]= "奇瑞"
local tb_wfxwdm = {}
tb_wfxwdm[0]= "00000" --"正常"
tb_wfxwdm[1]= "43060"--"低速"
--tb_wfxwdm[2]= "超速"
tb_wfxwdm[3]= "13010" --"逆行"
tb_wfxwdm[4]= "16251" --"闯红灯"
tb_wfxwdm[5]= "13451"--"压车道线"
tb_wfxwdm[6]= "12081" --"不按导向"
tb_wfxwdm[7]= "12110" --路口滞留
tb_wfxwdm[8]= "10760" --"机占非"
tb_wfxwdm[9]= "13451" --"违法变道"
tb_wfxwdm[10]= "12081" --"不按车道"
tb_wfxwdm[11]= "13445" --"违法禁令"
tb_wfxwdm[12]= "12110" --"路口停车"
tb_wfxwdm[13]= "12110" --"绿灯停车"

local tb_hpys = {}
tb_hpys[0] = 2 --"蓝色"
tb_hpys[1] = 1 --"黄色"
tb_hpys[2] = 0 --"白色"
tb_hpys[3] = 3 --"黑色"
tb_hpys[4] = 4 --"其它"
-------1定义公共组件（结束）----------------
module(...)
local version = '0.1'

---------------------------------------------
----开�?---


function get_version()
  return version
end
--------------
----------------------------成功 code=nil


----获得form_res 文件�? --2014/1/7 重构完成
function get_form_res(form)
  local res,err = form:parse()
  if not res then
    ngx.req.discard_body()  --清除�?   防止堵塞   不确定能不能清除成功
    return nil,err,1005
  end
  local form_res,err = form.fields
  if not form_res then
  ngx.req.discard_body()  --清除�?   防止堵塞   不确定能不能清除成功
    return nil,err,1006
  end
  return form_res,nil,nil
end


---获得storage_res --2014/1/7 重构完成
function get_storage(cjson_qz_group)
  local qz_storage_res = {}
  local qz_group_tables = cjson.decode(cjson_qz_group)
  local qz_tb_num  = tb_getn(qz_group_tables)
  local qz_group_num = math_random(1,qz_tb_num)
  local qz_store_path_index = qz_group_tables[qz_group_num].store_path_index
  qz_group_tables[qz_group_num].store_path_index =  math_random(1,qz_store_path_index) -1
  qz_storage_res = qz_group_tables[qz_group_num]
  --local group_name = group_tables[group_num].group_name
  return qz_storage_res,nil
end



----保存storage  --2014/1/7 重构完成
function save_storage(form_res,storage_res,tb_value,format)
  local gfile = ""
  
  
local storage_tb = {}
  local arg = tb_value
  local st = storage:new()
  st:set_timeout(arg.timeout)
  local ok,err = st:connect(storage_res)
  if not ok then
    return nil,err,1301
  end
  local res, err = st:upload_by_table(form_res.gfile1.value,form_res.gfile1.file_size,format)
  if not res then
    return nil,err,1302
  end
  gfile = res.group_name.."/"..res.file_name
--关闭storage
  local ok, err = st:set_keepalive(arg.keep_timeout,arg.keep_count)
  return gfile,nil,nil
end




---删除storage  --2014/1/7 重构完成
function del_storage(storage_res,tb_value,storage_tb)
  local arg = tb_value
  local st = storage:new()
  st:set_timeout(arg.timeout)
  local ok, err = st:connect(storage_res)
  if not ok then
    return nil,err,1100
  else
    local res,err = st:delete_file1(storage_tb.gfile1)
    if not res then
      return nil,err,1008
    end
  end
  --关闭storage
  local ok,err = st:set_keepalive(arg.keep_timeout,arg.keep_count)
  return "del storage is ok",nil,nil
end


function check_form_res(form_res)
  if form_res.type then
    if form_res.type.value == "sdk" then
      if not form_res.gfile1 then
        return nil,"sdk,not gfile1",1201
      end
      if not form_res.data then
        return nil,"sdk,not data",1202
      end
    elseif form_res.type.value == "ftp" then
      if not form_res.gfile1 then
        return nil,"ftp,not gfile1",1203
      end
    else
      return nil,"type is err",1204
    end
  else
    return nil,"type is nil",1205
  end
  return "ok"
end



function get_filename(filename)
  local file = string.gsub(filename,"\\","/")
  local tb = string.split(file,"/")
  local i = table.maxn(tb)
  local fname = tb[i]
  if i == 1 then
    return "",fname
  else
    local k = string.len(fname)+ 1
    local fpath = string.sub(file,1,-k)
    return fpath,fname
  end
end


function StringSplit(string,split)
  local list = {}
  local pos = 1
  if string.find("", split, 1) then -- this would result in endless loops
    return nil,"split matches empty string!"
  end
  while 1 do
    local first, last = string.find(string, split, pos)
    if first then -- found?
      table.insert(list, string.sub(string, pos, first-1))
      pos = last+1
    else
      table.insert(list, string.sub(string, pos))
      break
    end
  end
  return list
end



function createIconv(from,to,text)        ---编码转换

  local cd = iconv.new(to .. "//TRANSLIT", from)

  local ostr, err = cd:iconv(text)

  if err == iconv.ERROR_INCOMPLETE then
    return nil,"ERROR: Incomplete input."
  elseif err == iconv.ERROR_INVALID then
    return nil,"ERROR: Invalid input."
  elseif err == iconv.ERROR_NO_MEMORY then
    return nil,"ERROR: Failed to allocate memory."
  elseif err == iconv.ERROR_UNKNOWN then
    return nil,"ERROR: There was an unknown error."
  end
  return ostr
end

function ins_numbytime(k,sec)    ---按时间插入
  local key = k .. sec
  local incr_data = {}
  incr_data[key] = 1
 return  red_method.incr_data(incr_data)
  
end


function get_queue(cjson_queue,remote_ip)
  local tb_queue = cjson.decode(cjson_queue)
  local tb_return_queue = {}
  --local confignum,q_name,warningnum
  for _,v in pairs(tb_queue) do
    if  v.preclient == remote_ip then       --取到队列的名字与风险值
      tb_return_queue.confignum = v.confignum
      tb_return_queue.q_name = v.name
      tb_return_queue.warningnum = v.warningnum
      tb_return_queue.server_ip = v.postclient
      break
    end
  end
  if not tb_return_queue.q_name then
    return nil,"q_name is not found,remote_ip:"..remote_ip,1024        --code = 1024
  end
  
  return tb_return_queue,nil,nil
end









---------------------------------------------------------------------
--解析file
--传入参数（图像信息）
--输出 （含有所有信息的一个table）
function analysis_fname(fname)

local db_data = {}
local rt = StringSplit(fname,"-")
db_data.cd = rt[1]                              --车道
db_data.time = rt[2]                            --时间
db_data.zpxh = rt[3]                            --抓拍序号
db_data.txxh = string.sub(rt[13],-3,-1)         --图像序号取最后3个
if rt[4] == "" or rt[4]=="无车牌" then
  db_data.hphm = "无车牌"                         --号牌号码
else
  db_data.hphm = rt[4]
  local tb_reys = {"蓝","黄","白","黑"}
  for _,v in pairs(tb_reys) do
    local i = string.find(db_data.hphm,v)
    if i then
      db_data.hphm = string.gsub(db_data.hphm,v,"",1)
    end
  end
end
db_data.xssd = rt[6]     --行驶速度
local i,j = string.find(rt[15],"_")           --获取ip
db_data.cllk = string.sub(rt[15],1,i-1)
db_data.ip=rt[14]
local xs = config_table:get("xs_" ..db_data.ip) or "999999999"  --获取限速
db_data.zpzs = ipshine_table:get("zpzs_" ..db_data.ip) or "2"   --卡口抓拍张数为2
local per_xs = tonumber(db_data.xssd)/tonumber(xs)             --现在均为非高速公路
if tonumber(per_xs) > 1 then                                    --判断车速是否违法
  if tonumber(per_xs) < 1.2 then
    db_data.wfxwdmkk = "13030"
else
  if tonumber(per_xs) < 1.5 then
    db_data.wfxwdmkk = "13031"
  else
    if tonumber(per_xs) < 1.7 then
      db_data.wfxwdmkk = "16030"
    else
      if tonumber(per_xs) < 2 then
        db_data.wfxwdmkk = "16031"
      else
        db_data.wfxwdmkk = "16032"
      end
    end
  end
end
else
  db_data.wfxwdmkk = "00000"
end

db_data.wfxwdmdj = tb_wfxwdm[tonumber(rt[8])] or "00000" 
--车辆类型及归属地判断
--
db_data.hpys = tb_hpys[tonumber(rt[5])] or 4 
if tonumber(rt[5]) == 1 then    ---黄牌车,大型汽车
    db_data.hpzl = "1"
elseif tonumber(rt[5]) == 0 then
    db_data.hpzl = "2" ---蓝色车牌，小型车
elseif tonumber(rt[5]) == 2 then
    db_data.hpzl = "23"  ---白色车牌，临时入境车
else
    db_data.hpzl = "99" ---其他
end
utils.gcs_log("debug","号牌" ..cjson.encode(rt[5]) .."车牌" ..cjson.encode(db_data.hpzl))

if string.find(db_data.hphm,"鄂A") then  ---本地车
    db_data.clpz = "nat"    
else
    if db_data.hphm ~= "无车牌" then          ---外地车
        db_data.clpz = "wai"
    
    else
       db_data.clpz="other"  ---无车牌的车
    end
end
db_data.hpsztpzb = rt[9]                        --坐标
db_data.csys = tb_csys[tonumber(rt[10])] or "未知颜色"   --车身颜色
db_data.clpp = tb_clpp[tonumber(rt[11])] or "未知品牌"    --车辆品牌
db_data.lkbh = ipshine_table:get("lkbh_" ..db_data.ip)    --路口编号
db_data.xsfx = ipshine_table:get("xsfx_" ..db_data.ip)    --行驶方向
db_data.sbbh = ipshine_table:get("sbbh_" ..db_data.ip)  --设备编号
 
db_data.filename = fname
db_data.id = tostring(resty_uuid.gen20())
return db_data
end



function pack_kk(key,key1,db_data)
  local tb_key={key,key1}--key1为传过来的图片的键，key为要检查的键
  local db_data1={}
  local code=1 --判断缓存
  local status=0 --判断是否为同一组
  local time1=tonumber(db_data.time1)
  local res1,err=red_method.get_data(tb_key)
  if not res1 then
      utils.gcs_log("error",vssid .."检查缓存失败" ..err)
      return nil,nil,nil,err,1500
  end
  if res1[key1]~="" then --自身缓存存在，code=
      local res2=cjson.decode(res1[key1])
      local time2 = res2.time1 --缓存时间
      if time1<time2 then --缓存时间大于传过来的时间，传过来的图片是历史数据，返回db_data
          db_data1 = db_data
      elseif time1 > time2 then--缓存时间小于传过来的时间，缓存中的是历史数据，删除缓存，并将传过来的图片放入缓存
          db_data1 = res2
          local tb_key={key}
          red_method.del_data(tb_key)
          local red_data={}
          red_data[key1]=cjson.encode(db_data)
          local res,err=red_method.set_data(red_data) 
      end
     
  else--自身缓存不存在
      if res1[key]~="" then --存在同一组的图片
          local res2=cjson.decode(res1[key])
          local time2 = res2.time1
          local dictime=math_abs(tonumber(time2)-tonumber(time1))
          if dictime<=3000 then--是同一组的图片，一起打包
              if tonumber(time2)< tonumber(time1) then 
                  db_data1=res2
                  db_data1.gfile2 = db_data.gfile1
                  db_data1.tpmc2 = db_data.tpmc1
                  db_data1.time2 = db_data.time1
              else
                  db_data1=db_data
                  db_data1.gfile2 = res2.gfile1
                  db_data1.tpmc2 = res2.tpmc1
                  db_data1.time2 = res2.time1
              end
          else --不是同一组的图片
              if time1>time2 then--缓存时间小,将缓存打包
                  db_data1=res2
                  local tb_key={key} --清除缓存
                  red_method.del_data(tb_key)
                  local red_data={} --将自己放入缓存
                  red_data[key1]=cjson.encode(db_data)
                  local res,err=red_method.set_data(red_data)
                  if not res then
                      utils.gcs_log("error",vssid .."放入缓存失败" ..err)
                      return nil,err
                  end
                  utils.gcs_log("debug", vssid .."放入缓存成功" )  
              else--缓存时间大，将自身打包
                  db_data1=db_data
              end
          end
     else
          status=1
          local red_data={}
          red_data[key1]=cjson.encode(db_data)
          local res,err=red_method.set_data(red_data)
     end
  end
    return db_data1,status

end



function pack_checkself(key,db_data)
  local tb_key={key}
  local db_data1={}
  local code=""
  local status=""
  local time1=tonumber(db_data.time)
  local res1,err=red_method.get_data(tb_key)
  if not res1 then
      utils.gcs_log("error",vssid .."检查缓存失败" ..err)
      return nil,nil,nil,err,1500
  end
  if res1[key]~="" then --缓存存在，code=0
      
      local res2=cjson.decode(res1[key])
      local time2=tonumber(res2.time)--缓存时间
      code=0
      if time1<time2 then--传过来的图片是历史数据,status=0
          status=0
          db_data1=db_data
      else --缓存中的数据是历史数据,将传过来的图片放入缓存,status=1
          status=1
          db_data1=res2
          local tb_key={key}
          red_method.del_data(tb_key)
          local red_data={}
          red_data[key]=cjson.encode(db_data)
          local res,err=red_method.set_data(red_data)
          if not res then
              utils.gcs_log("error",vssid .."放入缓存失败" ..err)
              return nil,nil,nil,err
          end
          utils.gcs_log("debug",key .."放入缓存成功" )  
      end
       
  else--缓存不存在
      code=1
  end
    return db_data1,code,status
end
 


function pack_checkred(key,key1,db_data)
  local tb_key={key}
  local db_data1={}
  local code="" --缓存存在标志
  local status="" --是否是同一组标志
  local time1=tonumber(db_data.time)
  local res,err=red_method.get_data(tb_key)
  if not res then
      utils.gcs_log("error",vssid .."检查缓存失败" ..err)
      return nil,nil,nil,err,1500
  end
  if res[key]~="" then --存在 ，code=0
      local res=cjson.decode(res[key])
      local time2=tonumber(res.time)--缓存时间
      code=0
      local time3=(time2-time1)
      local dictime=math_abs(time3)
      if dictime<=3000 then 
          status=0 --是同一组
          db_data1=res
      else
          if time1>time2 then--缓存时间小,将缓存打包
              status=1
              db_data1=res
              local tb_key={key} --清除缓存
              red_method.del_data(tb_key)
              local red_data={} --将自己放入缓存
              red_data[key1]=cjson.encode(db_data)
              local res,err=red_method.set_data(red_data)
              if not res then
                  utils.gcs_log("error",vssid .."放入缓存失败" ..err)
              return nil,nil,nil,err
              end
              utils.gcs_log("debug", vssid .."放入缓存成功" )  
          else--缓存时间大，将自身打包
              status=-1
              db_data1=db_data
          end
         --不是同一组
      end
      
  else--缓存不存在
      code=1
      local red_data={}--将传过来的图片放入缓存
      red_data[key1]=cjson.encode(db_data)
      local res,err=red_method.set_data(red_data)
      if not res then
          utils.gcs_log("error",vssid .."放入缓存失败" ..err)
          return nil,nil,nil,err
      end
      utils.gcs_log("debug",vssid .. "放入缓存成功") 
  end
    return db_data1,code,status
end

function pack_kk3(res1,res2,res3)
  utils.gcs_log("debug",vssid .."开始打包")
  local db_data1={}
  local res2,res3=res2,res3
  db_data1=res1
  db_data1.id=db_data1.id
  db_data1.time1=db_data1.time
  db_data1.gfile1=db_data1.gfile
  db_data1.filename1=db_data1.filename
  db_data1.tpmc1=db_data1.tpmc
  db_data1.str_res1=db_data1.str_res
 
if res2 then  
  db_data1.time2=res2.time
  db_data1.gfile2=res2.gfile
  db_data1.filename2=res2.filename
  db_data1.tpmc2=res2.tpmc
  db_data1.str_res2=res2.str_res
  utils.gcs_log("debug",vssid .. "打包两张成功") 
end 

if res3 then
  db_data1.time3=res3.time
  db_data1.gfile3=res3.gfile
  db_data1.filename3=res3.filename
  db_data1.tpmc3=res3.tpmc
  db_data1.str_res3=res3.str_res
  utils.gcs_log("debug",vssid .. "打包三张成功")
end  
  db_data1.time=nil
  db_data1.gfile=nil
  db_data1.tpmc=nil
  db_data1.str_res=nil
  db_data1.filename=nil
  db_data1.size=nil
  db_data1.md5=nil
  utils.gcs_log("debug",vssid .."打包结束")
  return db_data1
end
function pack_kk2(res1,res3)
  utils.gcs_log("debug",vssid .."开始打包")
  local db_data1={}
  local res3=res3
  db_data1=res1
  db_data1.id=db_data1.id
  db_data1.time1=db_data1.time
  db_data1.gfile1=db_data1.gfile
  db_data1.filename1=db_data1.filename
  db_data1.tpmc1=db_data1.tpmc
  db_data1.str_res1=db_data1.str_res
 
if res3 then
  db_data1.time3=res3.time
  db_data1.gfile3=res3.gfile
  db_data1.filename3=res3.filename
  db_data1.tpmc3=res3.tpmc
  db_data1.str_res3=res3.str_res
  utils.gcs_log("debug",vssid .. "打包两张成功")
end  
  db_data1.time=nil
  db_data1.gfile=nil
  db_data1.tpmc=nil
  db_data1.str_res=nil
  db_data1.filename=nil
  db_data1.size=nil
  db_data1.md5=nil
  utils.gcs_log("debug","打包结束")
  return db_data1
end


function check_key(db_data,str)
  local key2=db_data.sbbh .."_" ..db_data.txxh .."_1"
  local key1=db_data.sbbh .."_" ..db_data.txxh .."_1_plate"
  local key_2=db_data.sbbh .."_" ..db_data.txxh .."_2"
  local key=""
  local hphm=db_data.hphm
  local zpxh=db_data.zpxh
  if hphm=="无车牌" then 
      if zpxh=="1" then 
          key=key2
      else
          key=key_2
      end
  else
      key=string.find(str,"Plate") and key1 or key2    
  end   
  return key 
end


function pack_stor(db_data,mongo_table_name,tb_queue_q_name)
  local mongo_table_name=mongo_table_name
  local list=tb_queue_q_name  
  utils.gcs_log("debug",vssid .. "进入存储流程")
  local ins_data={}
  ins_data[db_data.id]=cjson.encode(db_data)
  local res,err=red_method.set_data(ins_data)
  if not res then
      utils.gcs_log("error",vssid .. "插入缓存失败" ..err)
  end
  utils.gcs_log("debug",db_data.id .. "ins_data插入缓存成功")
  local n,err = mongo_method.save_data(mongo_table_name,db_data)
  if not n then 
      utils.gcs_log("error",vssid .."存储数据库出错" ..err)
  end
  local res,err,err_no=red_method.push("l",list,db_data.id)
  return n,res,err
end



